﻿using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace PlusPlusPaint.GUI
{
    class LayerPanel : Panel
    {
        #region member vars
        LayerPanelControl parentControl;
        Layers.LayerSummary layerSummary;
        bool layerVisible = true;
        Rectangle drawArea;
        #endregion

        #region properties
        public Layers.LayerSummary LayerSummary
        {
            get
            {
                return this.layerSummary;
            }
            set
            {
                this.layerSummary = value;
            }
        }

        public bool LayerVisible
        {
            get
            {
                return this.layerVisible;
            }
            set
            {
                this.layerVisible = value;
            }
        }
        #endregion

        #region constructors
        public LayerPanel(LayerPanelControl parent, Layers.LayerSummary lm)
        {
            this.parentControl = parent;
            this.layerSummary = lm;
            this.Size = new Size(110, 110);
            this.DoubleBuffered = true;
            this.Click += (object sender, EventArgs ea) => this.parentControl.SelectedLayerPanel = this;
            this.Paint += PaintLayer;
            this.createLayerPanelContent();
        }

        private void createLayerPanelContent()
        {
            drawArea = new Rectangle(5, 5, 100, 75);

            CheckBox layerVisibleBox = new CheckBox();
            layerVisibleBox.Location = new Point(10, 85);
            layerVisibleBox.Size = new Size(25, 25);
            layerVisibleBox.Checked = true;
            layerVisibleBox.MouseDown += (object sender, MouseEventArgs mea) => this.parentControl.SelectedLayerPanel = this;
            layerVisibleBox.CheckedChanged += (object sender, EventArgs ea) => this.parentControl.RequestChangeLayerVisibility(this, layerVisibleBox.Checked);

            Label layerNameLabel = new Label();
            layerNameLabel.Location = new Point(30, 90);
            layerNameLabel.Size = new Size(75, 20);
            if (LayerSummary.Name == "" || LayerSummary.Name == null)
            {
                layerNameLabel.Text = "Layer " + parentControl.Controls[0].Controls.Count.ToString();
                this.LayerSummary.Name = layerNameLabel.Text;
            }
            else
                layerNameLabel.Text = LayerSummary.Name;
            layerNameLabel.DoubleClick += changeLayerName;
            layerNameLabel.Click += (object sender, EventArgs ea) => this.parentControl.SelectedLayerPanel = this;

            this.Controls.Add(layerNameLabel);
            this.Controls.Add(layerVisibleBox);
        }
        #endregion

        #region eventhandlers
        private void PaintLayer(object sender, PaintEventArgs pea)
        {
            pea.Graphics.SmoothingMode = SmoothingMode.HighQuality;
            pea.Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality;
            pea.Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;

            pea.Graphics.FillRectangle(Brushes.White, drawArea);
            if (this.LayerSummary.VisualRepresentation != null)
            {
                Rectangle layerRect = layerSummary.ClientRectangle;
                pea.Graphics.DrawImage(createBoldImage(), calcDestinationRect(layerRect, drawArea), calcSourceRect(layerRect), GraphicsUnit.Pixel);
            }
            pea.Graphics.DrawRectangle(Pens.Black, drawArea);
        }
        #endregion

        #region private methods
        private void changeLayerName(object sender, EventArgs ea)
        {
            Label label = (Label)sender;
            TextBox textbox = new TextBox();
            textbox.Text = label.Text;
            Point location = label.Location;
            location.Offset(0, -2);
            textbox.Location = location;
            textbox.Size = label.Size;
            textbox.BorderStyle = BorderStyle.FixedSingle;
            textbox.KeyPress += (object o, KeyPressEventArgs kpea) => { if (kpea.KeyChar == (char)Keys.Enter) acceptLayerName(o, null); };
            textbox.Leave += acceptLayerName;
            label.Parent.Controls.Add(textbox);
            label.Parent.Controls.SetChildIndex(textbox, 0);
            label.Parent.Controls.Remove(label);
            textbox.Focus();
        }

        private void acceptLayerName(object sender, EventArgs ea)
        {
            TextBox textbox = (TextBox)sender;
            Label label = new Label();
            label.Text = textbox.Text;
            Point location = textbox.Location;
            location.Offset(0, 2);
            label.Location = location;
            label.Size = textbox.Size;
            label.DoubleClick += changeLayerName;
            textbox.Parent.Controls.Add(label);
            textbox.Parent.Controls.SetChildIndex(label, 0);
            textbox.Parent.Controls.Remove(textbox);
            this.LayerSummary.Name = label.Text;
        }

        private Rectangle calcSourceRect(Rectangle layerRect)
        {
            Size sketchSize = this.parentControl.SketchSize;
            int width = Math.Min(layerRect.Width + layerRect.X + 3, sketchSize.Width);
            int height = Math.Min(layerRect.Height + layerRect.Y + 3, sketchSize.Height);
            return new Rectangle(0, 0, width, height);
        }

        private Rectangle calcDestinationRect(Rectangle layerRect, Rectangle drawArea)
        {
            Size sketchSize = this.parentControl.SketchSize;
            int rectWidth = Math.Min((layerRect.X + layerRect.Width) * drawArea.Width / sketchSize.Width, drawArea.Width);
            int rectHeight = Math.Min((layerRect.Y + layerRect.Height) * drawArea.Height / sketchSize.Height, drawArea.Height);
            return new Rectangle(5, 5, rectWidth, rectHeight);
        }

        private Image createBoldImage()
        {
            Image layer = new Bitmap(this.LayerSummary.VisualRepresentation);
            Image result = new Bitmap(layer.Width + 3, layer.Height + 3);
            Graphics gr = Graphics.FromImage(result);
            for (int xCounter = -1; xCounter <= 1; xCounter++)
                for (int yCounter = -1; yCounter <= 1; yCounter++)
                    gr.DrawImageUnscaled(layer, xCounter, yCounter);
            return result;
        }
        #endregion
    }
}
